<script setup>
import {computed, ref, shallowRef, onMounted, onUnmounted} from "vue";
import {useMessage} from "naive-ui";
import {ArchiveTwotone, HideImageOutlined} from '@vicons/material'
import {processAndGenerateImage, unpackFrame} from "@/utils/unpackFrame/secondary.js";


const data = shallowRef([])
const binFileList = ref([])
const tableRef = ref(null)
const message = useMessage()
const csvName = ref("俯仰0.5")
const imgName = ref("星敏光斑")
const isLoading = ref(false)
const isImage = ref(false)
const imgUrl = ref("")

/**
 * 此版本解决丢帧问题, 升级方向为:1.多文件解析(表格分页展示)
 * @param file
 * @param maxWorkers
 * @returns {Promise<void>}
 */
const handleUploadFile = async ({file, maxWorkers = navigator.hardwareConcurrency | 8}) => {
	// 1.清除会触发一次2.上传也会触发
	if (file.status === "removed") {
		// 清空图片操作
		binFileList.value = []
		return
	}
	const startTime = performance.now()
	isLoading.value = true;
	const buffer = await file.file.arrayBuffer();
	console.time("处理");

	// **解析全部帧**
	const allFrames = unpackFrame(buffer); // 这一步返回的是 ArrayBuffer 数组
	const totalFrames = allFrames.length;

	// **计算分配策略**
	const chunkFrames = Math.ceil(totalFrames / maxWorkers); // 每个 worker 处理的帧数
	const results = new Array(maxWorkers);

	const runWorker = (index) => {
		return new Promise((resolve, reject) => {
			const start = index * chunkFrames;
			const end = Math.min(start + chunkFrames, totalFrames);
			const frameChunk = allFrames.slice(start, end); // 获取要分配的帧

			// **合并成一个大的 ArrayBuffer 传输**
			const mergedBuffer = new Uint8Array(frameChunk.length * 256);
			frameChunk.forEach((frame, i) => mergedBuffer.set(new Uint8Array(frame), i * 256));

			const worker = new Worker(new URL("@/utils/unpackFrame/worker.js", import.meta.url), {type: "module"});

			// **传输 buffer**
			worker.postMessage({chunk: mergedBuffer.buffer, frames: frameChunk.length}, [mergedBuffer.buffer]);

			worker.onmessage = (e) => {
				results[index] = e.data;
				worker.terminate();
				resolve();
			};

			worker.onerror = (error) => {
				console.error("Worker error:", error);
				worker.terminate();
				reject(error);
			};
		});
	};

	// **并行执行 Worker**
	await Promise.all([...Array(maxWorkers).keys()].map(runWorker));

	console.timeEnd("处理");

	// **合并所有 Worker 处理的结果**
	data.value = results.flat().map((res, index) => {
		res["序号"] = index + 1;
		return res;
	});

	isLoading.value = false;


	// **判断是否为图像数据只要任意一帧中有图像数据即可**
	if (data.value.some(obj => '图像数据' in obj && obj["图像数据"])) {
		isImage.value = true;
		try {
			imgUrl.value = await processImage(buffer);
		} catch (e) {
			message.error("生成图像错误,可能是数据帧不足以构建出图像!");
		}
	}

	message.success(`解析出 ${data.value.length} 帧, 耗时${parseInt(performance.now() - startTime)}ms`);
};


const processImage = async (buffer) => {
	// 处理图像数据
	console.log(buffer)
	const frames = unpackFrame(buffer)
	// 切片出图像数据
	const eb94Buffers = frames.map(f => f.slice(16, -112))
	const base64String = processAndGenerateImage(eb94Buffers, 320, 256)
	// 示例用法（假设你有一个 get_() 方法获取 dataList）
	console.log(base64String)// 示例用法（假设你有一个 get_() 方法获取 dataList）
	return base64String
}


// 创建标的列, 由生成数据的首行keys决定
const createCols = computed(() => {
	if (data.value.length === 0) return []
	// 提取首个数据的key当作列标题并添加序号列
	const keys = Object.keys({"序号": 1, ...data.value[0]})
	console.log(keys)

	return keys.sort((a) => a === "序号" ? -1 : 1).map((col, i) => {
		const defaultValue = {
			title: col,
			key: col,
			width: 200,
			fixed: i <= 1 ? "left" : i >= keys.length - 1 ? "right" : void 0
		}
		if (col === "图像数据") {
			// 此列数据过多,省略
			return {
				...defaultValue, ellipsis: {
					tooltip: true
				}
			}
		}
		return defaultValue
	})
})

/**
 * 点击触发下载csv
 * @param data csv数据来源
 * @returns {Promise<void>}
 */
const downloadCsv = async (data) => {
	// 去除掉序号列
	for (const dataIndex in data) {
		delete data[dataIndex]["序号"];
	}
	if (!data || data.length === 0) {
		message.warning("数据为空");
		return;
	}
	// 提取表头（Object.keys 获取 JSON 的键）
	const headers = Object.keys(data[0]);

	// 组装 CSV 内容
	const csvRows = [];
	csvRows.push(headers.join(",")); // 添加表头
	data.forEach(row => {
		csvRows.push(headers.map(key => row[key]).join(",")); // 添加每行数据
	});

	// 转换为 CSV 字符串
	let csvContent = csvRows.join("\n");

	// **添加 UTF-8 BOM 防止中文乱码**
	const bom = "\uFEFF"; // UTF-8 BOM
	const csvBlob = new Blob([bom + csvContent], {type: "text/csv;charset=utf-8;"});

	// 创建下载链接
	const csvUrl = URL.createObjectURL(csvBlob);
	const link = document.createElement("a");
	link.href = csvUrl;
	link.download = csvName.value + ".csv";
	document.body.appendChild(link);
	link.click();

	// 清理 URL 对象
	document.body.removeChild(link);
	URL.revokeObjectURL(csvUrl);
};

/**
 * 点击按钮触发图像下载
 */
const downloadImg = () => {
	const link = document.createElement("a");
	link.href = imgUrl.value;
	link.download = `${imgName}.png`; // 自定义文件名
	document.body.appendChild(link);
	link.click();
	document.body.removeChild(link);
}
const isShiftPressed = ref(false)

const handleKeyDown = (event) => {
	if (event.key === 'Shift') {
		isShiftPressed.value = true
	}
}

const handleKeyUp = (event) => {
	if (event.key === 'Shift') {
		isShiftPressed.value = false
	}
}

// 表格滚动前纵向初始值
let virtualListScrollTop = 0
const handleWheel = (event) => {
	// 获取虚拟列表的dom元素
	const virtualList = tableRef.value.$el.querySelector('.v-vl')
	if (virtualListScrollTop === 0) virtualListScrollTop = virtualList.scrollTop // 记录滚动前纵向初始值

	if (isShiftPressed.value && tableRef.value) {
		event.preventDefault() // 阻止默认纵向滚动
		if (virtualList) {
			virtualList.scrollLeft += event.deltaY // 使用滚轮上下滚动控制横向滚动
			virtualList.scrollTop = virtualListScrollTop // 在横向滚动时纵向不受影响
		}
	}
}

// 图片组件的实例
const previewImageRef = ref(null)


onMounted(() => {
	window.addEventListener('keydown', handleKeyDown)
	window.addEventListener('keyup', handleKeyUp)
	window.addEventListener('wheel', handleWheel, {passive: false}) // passive: false 允许 preventDefault()
})

onUnmounted(() => {
	window.removeEventListener('keydown', handleKeyDown)
	window.removeEventListener('keyup', handleKeyUp)
	window.removeEventListener('wheel', handleWheel)
})

</script>

<template>
	<n-layout class="h-full" content-class="h-full flex gap-4 flex-col">
		<n-flex :wrap="false" class="h-1/6">
			<n-upload
				directory-dnd
				v-model:file-list="binFileList"
				:on-change="handleUploadFile"
				class="w-2/4 h-full flex gap-2"
				trigger-class="flex-1"
				file-list-class="mt-0"
			>
				<n-flex class="w-full" :wrap="false">
					<n-upload-dragger class="p-4 w-full">
						<div>
							<n-icon size="48" :depth="3">
								<ArchiveTwotone/>
							</n-icon>
						</div>
						<n-text style="font-size: 16px">
							点击或者拖动文件到该区域来上传
							<n-text tag="div" depth="3">仅支持光学头
								<n-text type="warning">(扫捕跟,星敏,跟踪相机)</n-text>
							</n-text>
						</n-text>
					</n-upload-dragger>
				</n-flex>
			</n-upload>
			<n-card class="w-2/4 h-full" content-class="flex gap-2 flex-col">
				<n-flex align="center">
					<n-text class="text-base">文件名称:</n-text>
					<n-input class="w-48" v-model:value="csvName">
						<template #suffix>
							<n-text depth="3">.csv</n-text>
						</template>
					</n-input>
					<n-button @click="downloadCsv(data)" :disabled="data.length === 0">导出CSV文件</n-button>
					<n-button @click="data=[]" type="error">清空表格</n-button>
				</n-flex>
				<n-flex align="center" v-if="isImage">
					<n-text class="text-base">图像名称:</n-text>
					<n-input class="w-48" v-model:value="imgName">
						<template #suffix>
							<n-text depth="3">.png</n-text>
						</template>
					</n-input>
					<n-button
						@click="downloadImg"
						:disabled="data.length === 0">下载图像文件
					</n-button>
					<n-button type="info" @click="previewImageRef.click();console.log(previewImageRef)">预览图像
					</n-button>
					<n-image
						width="40" height="40" title="点击预览图像"
						class="shadow shadow-blue-900"
						:src="imgUrl" ref="previewImageRef">
						<template #placeholder>
							<n-icon :component="HideImageOutlined" size="30"></n-icon>
						</template>
					</n-image>
				</n-flex>
			</n-card>

		</n-flex>
		<n-flex class="h-5/6 mb-1">
			<n-data-table
				:bordered="false"
				:single-line="false"
				:loading="isLoading"
				class="h-full w-full"
				ref="tableRef"
				:columns="createCols"
				virtual-scroll-x
				:min-row-height="52"
				:data="data"
				scroll-x="1400"
				flex-height
				virtual-scroll
				:scrollbar-props="{
					trigger: 'none',
				}"
			/>
		</n-flex>
	</n-layout>
</template>

<style>
/*
使图像像素化,便于看光斑质量
 */
.n-image-preview {
	image-rendering: pixelated;
	image-rendering: crisp-edges; /* 兼容性 */
	width: 100vw; /* 放大尺寸 */
	height: auto;
}

/* 横向 */
.n-scrollbar-rail--horizontal .n-scrollbar-rail__scrollbar {
	height: 6px !important;
	background-color: rgb(96, 96, 96) !important; /* 控制滚动条颜色 */
	border-radius: 5px !important; /* 滚动条圆角 */
}

/*纵向*/
.n-scrollbar-rail--vertical .n-scrollbar-rail__scrollbar {
	width: 7px !important;
	height: 70px !important;
	background-color: rgb(81, 81, 81) !important; /* 控制滚动条颜色 */
	border-radius: 5px !important; /* 滚动条圆角 */
}

</style>